import CodeView from '../../../shared/components/CodeView';
import DisplayColumn from '../../../shared/components/DisplayColumn';
import DisplayGrid from '../../../shared/components/DisplayGrid';
import Blockquote from '../../../shared/components/Blockquote';
import RequiredLabelExample from '../../../shared/components/RequiredLabelExample';
import { getDisplayElementById, getDemoStylesById } from '../../shared/helpers';
import * as Base from './base/example';
import * as Range from './range/example';

<div className="doc lead">
  A datepicker is a text input to capture a date. You can select a single date, date range or date and time.
</div>

<CodeView exampleOnly demoStyles={getDemoStylesById(Base.default)}>
  {getDisplayElementById(Base.default)}
</CodeView>

## About Datepickers

### Implementation

The datepicker is a [form element](/components/form-element), containing a label and text [input](/components/input), and a dropdown [menu](/components/menus), containing a grid-based calendar and filters. The form element acts as a trigger for the dropdown.

<Blockquote type="warning">
  <p>
    Placement of inline form elements inside a data table cell is not supported. Instead, use a button to invoke a popover, which does support form elements.
  </p>
</Blockquote>

The datepicker has the following markup requirements:

**Desktop:**
  - Add `.slds-is-open` to the element with `.slds-dropdown-trigger` to invoke the dropdown that contains the datepicker.
  - The `.slds-is-selected` modifier class is required on the `td` element that has the selected day.
  - The `.slds-is-today` modifier class is required on the `td` element that is the current day.
  - The `.slds-has-multi-selection` modifier class is required on the `tr` element that contains multiple days selected in the **same** week.
  - The `.slds-has-multi-row-selection` modifier class is required on any `tr` element that contains multiple days selected in the **multiple** weeks.
  - The `.slds-is-selected-multi` modifier class is required on the `td` element that contains a selected day within a range.

**Mobile:**
  - When on mobile, we want to leverage the native date picker by changing the `input` type from `text` to `date`
  - The `input type="date"` will create an input field allowing a date and time to be easily entered — this includes year, month, day.
  - When switching `input type="text"` to `input type="date"` for mobile, we need to remove the ARIA attributes. The native rendering doesn't require these.
    - On the element with the class `slds-combobox`, please remove `role="combobox"`, `aria-expanded`, and `aria-haspopup`.
    - On the `input` that we just added `type="date"` to, please remove `aria-controls`, `aria-autocomplete`, and `role="textbox"`.

### Accessibility

To display the datepicker text input field and calendar date picker with maximum accessibility, datepicker should be empty to start. When a user begins typing, text input is activated, and the full date format for the user’s locale, such as text DD MM YYYY in the en_US_locale.

#### Markup

**Dialog:**

  - Should act as a focus trap so the user only cycles through the datepicker `dialog` when the datepicker is open
  - A Date Format Visible variation displays a message about the expected date format. When the date field receives focus, a message appears under the field to show the expected date format. When focus is removed from the date field, the message is hidden and available as assistive text.
  - All datepicker fields marked as required with an * must have an accompanying legend. Example:
    <RequiredLabelExample/>

**Grid:**

  - Table must be labelled with `role="grid"` and be appropriately labelled with `aria-labelledby`
  - Use `aria-multiselectable="true"` to allow for selection of multiple days
  - Should act as a single focus stop

**Gridcell:**

  - All dates should have `role="gridcell"` and `aria-selected="false"` on the `gridcell` by default
  - If a date is selected, `aria-selected` should be set to `true` on the corresponding `gridcell`
  - `aria-current` is used to indicate which day is today and should be set to `aria-current="date"`
  - `aria-label` is used to provide the full `DD MM YYYY` text of the date

**Opening the Datepicker:**

  - Mouse user: open the datepicker when a mouse user clicks on the input
  - Keyboard user: only open the datepicker when a keyboard user presses `enter` or `space` on the datepicker button
    - Do not open the datepicker when user focus is on the input

**Closing the Datepicker:**

  - Keyboard user: after closing the calendar, the focus should go to the input. The focus on input directs screen reader to output the selected date.
    - The focus should not go on the calendar icon button that triggered the calendar to open.

#### Keyboard Interactions

  - When the datepicker opens, place user focus on either the currently selected date in the grid or if no date is selected the current day
  - `left` and `right` arrow keys to navigate row
  - `up` and `down` arrow keys to navigate between weeks on the same day
  - `home` and `end` keys to jump to beginning or end of current row
  - `pagedown` and `pageup` to navigate between months
  - `alt + pagedown` and `alt + pageup` to navigate between years
  - `enter` to select date and close datepicker
  - `esc` to close datepicker without choosing a date

## Base
<CodeView demoStyles={getDemoStylesById(Base.default)}>
  {getDisplayElementById(Base.default)}
</CodeView>

### States

#### Date Selected
<CodeView demoStyles={getDemoStylesById(Base.states, 'datepicker-day-selected')}>
  {getDisplayElementById(Base.states, 'datepicker-day-selected')}
</CodeView>

#### Date Picker Has Error
<CodeView demoStyles={getDemoStylesById(Base.states, 'datepicker-with-error')}>
  {getDisplayElementById(Base.states, 'datepicker-with-error')}
</CodeView>

#### Date Required
<CodeView demoStyles={getDemoStylesById(Base.states, 'datepicker-required')}>
  {getDisplayElementById(Base.states, 'datepicker-required')}
</CodeView>

#### Date Required, Date Picker Has Error
<CodeView demoStyles={getDemoStylesById(Base.states, 'datepicker-required-with-error')}>
  {getDisplayElementById(Base.states, 'datepicker-required-with-error')}
</CodeView>

### Date Format Visible
<CodeView demoStyles={getDemoStylesById(Base.states, 'date-format-visible')}>
  {getDisplayElementById(Base.states, 'date-format-visible')}
</CodeView>

## Range
<CodeView demoStyles={getDemoStylesById(Range.default)}>
  {getDisplayElementById(Range.default)}
</CodeView>

### States

#### Start Date Selected
<CodeView demoStyles={getDemoStylesById(Range.states, 'start-date')}>
  {getDisplayElementById(Range.states, 'start-date')}
</CodeView>

#### End date selected (Same week)
<CodeView demoStyles={getDemoStylesById(Range.states, 'end-date-week')}>
  {getDisplayElementById(Range.states, 'end-date-week')}
</CodeView>

#### End date selected (Different week)
<CodeView demoStyles={getDemoStylesById(Range.default)}>
  {getDisplayElementById(Range.default)}
</CodeView>

#### Today - In selected range
<CodeView demoStyles={getDemoStylesById(Range.default)}>
  {getDisplayElementById(Range.default)}
</CodeView>

#### Current And Adjacent Month In Selected Range
<CodeView demoStyles={getDemoStylesById(Range.default)}>
  {getDisplayElementById(Range.default)}
</CodeView>
